PAGE 118,121
TITLE PRT ------ 01/10/86 PRINTER ADAPTER BIOS
.XLIST
INCLUDE POSTEQU.INC
INCLUDE DSEG.INC
.LIST
CODE	SEGMENT BYTE PUBLIC

	PUBLIC	PRINTER_IO_1
	EXTRN	DDS:NEAR

;--- INT  17 H -----------------------------------------------------------------
; PRINTER_IO								       :
;	THIS ROUTINE PROVIDES COMMUNICATION WITH THE PRINTER		       :
; INPUT 								       :
;	(AH)= 00H  PRINT THE CHARACTER IN (AL)				       :
;		    ON RETURN, (AH)= 1 IF CHARACTER NOT PRINTED (TIME OUT)     :
;		    OTHER BITS SET AS ON NORMAL STATUS CALL		       :
;	(AH)= 01H  INITIALIZE THE PRINTER PORT				       :
;		    RETURNS WITH (AH) SET WITH PRINTER STATUS		       :
;	(AH)= 02H  READ THE PRINTER STATUS INTO (AH)			       :
;		   7	  6	 5	4      3      2-1    0		       :
;		   |	  |	 |	|      |      |      |_ 1 = TIME OUT   :
;		   |	  |	 |	|      |      | 		       :
;		   |	  |	 |	|      |      |_ UNUSED 	       :
;		   |	  |	 |	|      |			       :
;		   |	  |	 |	|      |_ 1 = I/O ERROR 	       :
;		   |	  |	 |	|				       :
;		   |	  |	 |	|_ 1 = SELECTED 		       :
;		   |	  |	 |					       :
;		   |	  |	 |_ 1 = OUT OF PAPER			       :
;		   |	  |						       :
;		   |	  |_ 1 = ACKNOWLEDGE				       :
;		   |							       :
;		   |_ 1 = NOT BUSY					       :
;									       :
;	(DX) = PRINTER TO BE USED (0,1,2) CORRESPONDING TO ACTUAL VALUES       :
;		IN @PRINTER_BASE AREA					       :
; DATA AREA @PRINTER_BASE CONTAINS THE BASE ADDRESS OF THE PRINTER CARD(S)     :
; AVAILABLE (LOCATED AT BEGINNING OF DATA SEGMENT, 408H ABSOLUTE, 3 WORDS)     :
;									       :
; DATA AREA @PRINT_TIM_OUT (BYTE) MAY BE CHANGE TO CAUSE DIFFERENT	       :
; TIME OUT WAITS. DEFAULT=20 * 4					       :
;									       :
; REGISTERS	(AH) IS MODIFIED WITH STATUS INFORMATION		       :
;		ALL OTHERS UNCHANGED					       :
;-------------------------------------------------------------------------------
	ASSUME	CS:CODE,DS:DATA

PRINTER_IO_1	PROC	FAR		; ENTRY POINT FOR ORG 0EFD2H

	STI				; INTERRUPTS BACK ON
	PUSH	DX			; SAVE WORK REGISTERS
	PUSH	BX
	CMP	DX,03H			; CHECK FOR PRINTER NUMBER VALID 0-3
	JA	B10			; ERROR EXIT IF OUT OF RANGE

	MOV	BH,AL			; SAVE CHARACTER TO BE PRINTED
	PUSH	DS			; SAVE SEGMENT
	CALL	DDS			; ADDRESS DATA SEGMENT

	PUSH	SI			; SAVE WORK POINTER REGISTER
	MOV	SI,DX			; GET PRINTER PARAMETER
	MOV	BL,@PRINT_TIM_OUT[SI]	; LOAD TIMEOUT VALUE
	SHL	SI,1			; WORD OFFSET INTO TABLE INTO (SI)
	MOV	DX,@PRINTER_BASE[SI]	; GET BASE ADDRESS FOR PRINTER CARD
	POP	SI			; RECOVER CALLERS (SI) REGISTER
	POP	DS			;  AND (DS) SEGMENT REGISTER
	ASSUME	DS:NOTHING
	OR	DX,DX			; TEST DX = ZERO, INDICATING NO PRINTER
	JZ	B10			; EXIT, NO PRINTER ADAPTER AT OFFSET

	OR	AH,AH			; TEST FOR (AH)= 00H
	JZ	B30			;  PRINT CHARACTER IN (AL)

	DEC	AH			; TEST FOR (AH)= 01H
	JZ	B80			;  INITIALIZE PRINTER

	DEC	AH			; TEST FOR (AH)= 02H
	JZ	B60			;  GET PRINTER STATUS
B10:
	MOV	AH,029H 		; RETURN ERROR BITS FOR INVALID CALLS
B20:
	POP	BX			; RETURN
	POP	DX			; RECOVER REGISTERS
	IRET				; RETURN TO CALLING PROGRAM

;-----	PRINT THE CHARACTER IN (AL)

B30:
	OUT	DX,AL			; OUTPUT CHARACTER TO DATA PORT
	INC	DX			; POINT TO STATUS PORT
PAGE
;-----	CHECK FOR PRINTER BUSY

	IN	AL,DX			; PRE-CHARGE +BUSY LINE IF FLOATING
	IN	AL,DX			; GET STATUS PORT VALUE
	TEST	AL,80H			; IS THE PRINTER CURRENTLY BUSY
	JNZ	B40			; SKIP SYSTEM DEVICE BUSY CALL IF NOT

;-----	INT 15 H -- DEVICE BUSY

	MOV	AX,90FEH		; FUNCTION 90 PRINTER ID
	INT	15H			; SYSTEM CALL

;-----	WAIT BUSY
					; ADJUST OUTER LOOP COUNT
B40:
	PUSH	CX			; SAVE CALLERS (CX) REGISTER
	SUB	CX,CX			; INNER LOOP (64K)
B45:
	IN	AL,DX			; GET STATUS
	MOV	AH,AL			; STATUS TO (AH) ALSO
	TEST	AL,80H			; IS THE PRINTER CURRENTLY BUSY
	JNZ	B50			; GO TO OUTPUT STROBE

	LOOP	B45			; LOOP IF NOT

	DEC	BL			; DECREMENT OUTER LOOP COUNT
	JNZ	B45			; MAKE ANOTHER PASS IF NOT ZERO

	POP	CX			; RESTORE CALLERS (CX) VALUE
	OR	AH,1			; SET ERROR FLAG
	AND	AH,0F9H 		; TURN OFF THE UNUSED BITS
	JMP	SHORT B70		; RETURN WITH ERROR FLAG SET

B50:					;	  SEND STROBE PULSE
	POP	CX			; RESTORE CALLERS (CX) VALUE
	MOV	AL,0DH			; SET THE STROBE LOW (BIT ON)
	INC	DX			; OUTPUT STROBE TO CONTROL PORT
	CLI				; PREVENT INTERRUPT PULSE STRETCHING
	OUT	DX,AL			; OUTPUT STROBE BIT   > 1us  < 5us
	JMP	$+2			; I/O DELAY TO ALLOW FOR LINE LOADING
					;  AND FOR CORRECT PULSE WIDTH
	MOV	AL,0CH			; SET THE -STROBE HIGH
	OUT	DX,AL
	STI				; INTERRUPTS BACK ON
	DEC	DX			; ADJUST BACK TO BASE ADDRESS
	DEC	DX			;  FOR OUTPUT ROUTINE

;-----	PRINTER STATUS

B60:
	INC	DX			; POINT TO CONTROL PORT
	IN	AL,DX			; PRE-CHARGE +BUSY LINE IF FLOATING
	IN	AL,DX			; GET PRINTER STATUS HARDWARE BITS
	AND	AL,0F8H 		; TURN OFF UNUSED BITS
	MOV	AH,AL			; SAVE

B70:
	MOV	AL,BH			; RECOVER CHARACTER INTO (AL) REGISTER
	XOR	AH,48H			; FLIP A COUPLE OF BITS
	JMP	B20			; RETURN FROM ROUTINE WITH STATUS IN AH

;-----	INITIALIZE THE PRINTER PORT

B80:
	INC	DX			; POINT TO OUTPUT PORT
	INC	DX
	MOV	AL,8			; SET INIT LINE LOW
	OUT	DX,AL
	MOV	AX,1000 		; ADJUST FOR INITIALIZATION DELAY LOOP
B90:					; INIT_LOOP
	DEC	AX			; LOOP FOR RESET TO TAKE
	JNZ	B90			; INIT_LOOP

	MOV	AL,0CH			; NO INTERRUPTS, NON AUTO LF, INIT HIGH
	OUT	DX,AL
	DEC	DX			; ADJUST BACK TO BASE ADDRESS
	DEC	DX			;  FOR OUTPUT ROUTINE
	JMP	B60			; EXIT THROUGH STATUS ROUTINE

PRINTER_IO_1	ENDP

	CODE	ENDS
	END
